using UnityEngine;
using UnityEngine.Rendering;
// ReSharper disable All

public partial class CameraRenderer
{
    const string bufferName = "Render Camera"; //命令缓冲区名字

    static ShaderTagId
        unlitShaderTagId = new ShaderTagId("SRPDefaultUnlit"),
        litShaderTagId = new ShaderTagId("CustomLit"); //自定义着色器类型


    static int frameBufferId = Shader.PropertyToID("_CameraFrameBuffer");
    CommandBuffer buffer = new CommandBuffer
    {
        name = bufferName
    }; //命令缓冲区属性

    ScriptableRenderContext context;
    Camera camera;
    CullingResults cullingResults;
    Lighting lighting = new Lighting();
    PostFXStack postFXStack = new PostFXStack();

    public void Render(
        ScriptableRenderContext context, Camera camera,
        bool useDynamicBatching, bool useGPUInstancing, bool useLightsPerObject,
        ShadowSettings shadowSettings, PostFXSettings postFXSettings)
    {
        this.context = context;
        this.camera = camera;
        PrepareBuffer();
        PrepareForSceneWindow();
        if (!Cull(shadowSettings.maxDistance))
        {
            return;
        }

        buffer.BeginSample(SampleName);
        ExecuteBuffer();
        lighting.Setup(
			context, cullingResults, shadowSettings, useLightsPerObject);
        postFXStack.Setup(context, camera, postFXSettings);
        buffer.EndSample(SampleName);
        Setup();
        DrawVisibleGeometry(
			useDynamicBatching, useGPUInstancing, useLightsPerObject);
        DrawUnsupportedShaders();
        DrawGizmosBeforeFX();
        if (postFXStack.IsActive)
        {
            postFXStack.Render(frameBufferId);
        }
        DrawGizmosAfterFX();
        Cleanup();
        Submit();
    }

    /// <summary>
    /// 剔除摄像机外信息
    /// </summary>
    /// <returns></returns>
    bool Cull(float maxShadowDistance)
    {
        if (camera.TryGetCullingParameters(out ScriptableCullingParameters p))
        {
            p.shadowDistance = Mathf.Min(maxShadowDistance, camera.farClipPlane);
            cullingResults = context.Cull(ref p);
            return true;
        }

        return false;
    }

    /// <summary>
    /// 设置到屏幕的投影矩阵及其他设定
    /// </summary>
    void Setup()
    {
        //设置投射到屏幕的矩阵
        context.SetupCameraProperties(camera);
        //清理标签
        CameraClearFlags flags = camera.clearFlags;
        //执行PostFX
        if (postFXStack.IsActive)
        {
            if (flags > CameraClearFlags.Color)
            {
                flags = CameraClearFlags.Color;
            }

            buffer.GetTemporaryRT(
                frameBufferId, camera.pixelWidth, camera.pixelHeight,
                32, FilterMode.Bilinear, RenderTextureFormat.Default
            );
            buffer.SetRenderTarget(
                frameBufferId,
                RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store
            );
        }


        //清理命令缓冲区，清理旧渲染信息（深度，颜色数据，清除的颜色）
        buffer.ClearRenderTarget(
            flags <= CameraClearFlags.Depth,
            flags == CameraClearFlags.Color,
            flags == CameraClearFlags.Color ?
			camera.backgroundColor.linear : Color.clear);
        //开始命令缓冲区
        buffer.BeginSample(SampleName);
        //执行命令缓冲区
        ExecuteBuffer();
    }
	void Cleanup()
    {
        lighting.Cleanup();
        if (postFXStack.IsActive)
        {
            buffer.ReleaseTemporaryRT(frameBufferId);
        }
    }
    /// <summary>
    /// 提交渲染
    /// </summary>
    void Submit()
    {
        //结束命令缓冲区
        buffer.EndSample(SampleName);
        //执命令行缓冲区
        ExecuteBuffer();
        //提交渲染操作
        context.Submit();
    }

    /// <summary>
    /// 执行命令缓冲区
    /// /// </summary>
    void ExecuteBuffer()
    {
        context.ExecuteCommandBuffer(buffer);
        buffer.Clear();
    }


    /// <summary>
    ///绘制几何图形
    /// </summary>
    void DrawVisibleGeometry(
        bool useDynamicBatching, bool useGPUInstancing, bool useLightsPerObject)
    {
        //绘制可见图形
        //绘制不透明物体
        PerObjectData lightsPerObjectFlags = useLightsPerObject ? 
			PerObjectData.LightData | PerObjectData.LightIndices : 
			PerObjectData.None;
        var sortingSettings = new SortingSettings(camera)
        {
            criteria = SortingCriteria.CommonOpaque
        };
        var drawingSettings = new DrawingSettings(
            unlitShaderTagId, sortingSettings
        )
        {
            enableDynamicBatching = useDynamicBatching,
            enableInstancing = useGPUInstancing,
            perObjectData =
                PerObjectData.ReflectionProbes |
                PerObjectData.Lightmaps | PerObjectData.ShadowMask |
                PerObjectData.LightProbe | PerObjectData.OcclusionProbe |
                PerObjectData.LightProbeProxyVolume |
                PerObjectData.OcclusionProbeProxyVolume |
                lightsPerObjectFlags
        };
        drawingSettings.SetShaderPassName(1, litShaderTagId);
        var filteringSettings = new FilteringSettings(RenderQueueRange.opaque);
        context.DrawRenderers(
            cullingResults, ref drawingSettings, ref filteringSettings);

        //绘制天空
        context.DrawSkybox(camera);

        //绘制透明物体
        sortingSettings.criteria = SortingCriteria.CommonTransparent;
        drawingSettings.sortingSettings = sortingSettings;
        filteringSettings.renderQueueRange = RenderQueueRange.transparent;
        context.DrawRenderers(
            cullingResults, ref drawingSettings, ref filteringSettings);
    }

    
}